home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / UTILITY / INTER29A.ARJ / INTPRINT.C < prev    next >
C/C++ Source or Header  |  1992-02-09  |  28KB  |  1,010 lines

  1. /***********************************************************************/
  2. /* INTPRINT.C by Ralf Brown.  Donated to the Public Domain.           */
  3. /* Please do not remove my name from any copies or derivatives.        */
  4. /***********************************************************************/
  5. /* Program History:                               */
  6. /*   v1.00  4/23/89  initial public release                   */
  7. /*             with 4/30/89 list                       */
  8. /*   v1.10  5/21/89  added -I and -f                       */
  9. /*   v1.11  1/6/90   fixed #endif's for compilers which don't handle   */
  10. /*             labels                           */
  11. /*   v1.20  6/8/90   added -r                           */
  12. /*   v1.30  7/14/90  added -b, tables now stay aligned on odd indents  */
  13. /*   v1.40  10/6/90  added -B based on changes by Naoto Kimura, -w     */
  14. /*   v1.40a 5/6/91   HP LaserJet II support by Russ Herman           */
  15. /*   v1.41  7/9/91   HP PCL support by P.J.Farley III               */
  16. /*   v2.00  9/1/91   modular printer definitions               */
  17. /*             printing multipart interrupt list               */
  18. /*   v2.01  2/9/92   fixed summary entry for non-numeric AX= and AH=   */
  19. /*             smarter page breaks                   */
  20. /***********************************************************************/
  21. /* Recompiling:                                */
  22. /*   Turbo C / Borland C++                           */
  23. /*    tcc -mt -lt -Z -p intprint                       */
  24. /***********************************************************************/
  25.  
  26. #include <stdio.h>
  27. #include <string.h>
  28.  
  29. #define VERSION "2.01"
  30.  
  31. #define MAXLINE 81   /* at most 80 chars per line (plus newline) */
  32. #define MAXPAGE 200  /* at most 200 lines per page */
  33.  
  34. #ifndef FALSE
  35. #define FALSE 0
  36. #endif
  37. #ifndef TRUE
  38. #define TRUE !FALSE
  39. #endif
  40.  
  41. #ifdef __TURBOC__
  42. #  define PROTOTYPES
  43. #  include <stdlib.h>
  44. int _Cdecl isatty(int handle) ;
  45. void _setenvp(void) {} /* don't need the environment, so don't include it */
  46. int isspace(char c) { return (c == ' ' || c == '\t') ; }
  47. #else
  48. /*#define PROTOTYPES  /* uncomment if compiler supports ANSI-style prototypes */
  49. #define NEED_STRNICMP /* comment out if library contains strnicmp() */
  50. #define _Cdecl
  51. #  include <ctype.h>
  52.  
  53. char *itoa(num,buf,radix)   /* not everybody has the same itoa() as TurboC */
  54. int num ;            /* minimal implementation */
  55. char *buf ;
  56. int radix ;
  57. {
  58.    int count = 0 ;
  59.    int i ; 
  60.    char tmp ;
  61.  
  62.    do {
  63.       buf[count++] = '0' + num % radix ;
  64.       num = num / radix ;
  65.    } while (num) ;
  66.    buf[count] = '\0' ;
  67.    if (count > 1)
  68.       for (i = 0 ; i < count / 2 ; i++)
  69.      {
  70.      tmp = buf[i] ;
  71.      buf[i] = buf[count-i-1] ;
  72.      buf[count-i-1] = tmp ;
  73.      }
  74.    return buf ;
  75. }
  76. #endif /* __TURBOC__ */
  77.  
  78. /***********************************************/
  79.  
  80. typedef struct _cstr         /* a counted string */
  81.    {
  82.    int len ;             /* the string's length */
  83.    char *str ;             /* the actual contents of the string */
  84.    } cstr ;
  85.  
  86. #define CSTR(s) { sizeof(s)-1, (s) }  /* for defining a counted string literal */
  87. #define cstrlen(s) ((s)->len)     /* how long is the counted string? */
  88. #define cstrchar(s,i) ((s)->str[i])  /* retrieve a character from a counted string */
  89.  
  90. typedef struct _printer_def
  91.    {
  92.    char *name ;         /* for selecting the appropriate printer */
  93.    cstr init1, init2 ;        /* initialization strings */
  94.    cstr marginl, marginc, marginr ; /* margins: duplex even, non-duplex, duplex odd */
  95.    cstr duplex_on ;        /* turn on duplex mode */
  96.    cstr term1, term2 ;        /* cleanup strings */
  97.    cstr bold_on, bold_off ;    /* boldface on/off */
  98.    int indent ;         /* how many extra spaces to indent */
  99.    int lines_per_page ;     /* how many lines to print on each page */
  100.    int page_length ;        /* how many lines on each page */
  101.    int page_width ;        /* how many printable columns per line? */
  102. #ifdef PROTOTYPES
  103.    void (*put_line)(FILE *,int) ;/* function to call to print out divider line */
  104. #else
  105.    void (*put_line)() ;     /* function to call to print out divider line */
  106. #endif /* PROTOTYPES */
  107.    int *flag ;            /* flag to set when using this printer definition */
  108.    } PRINTER_DEF ;
  109.  
  110. /***********************************************/
  111.  
  112. #ifdef PROTOTYPES
  113. void usage(void) ;
  114. void fatal(char *msg) ;
  115. void get_line(char *buf,int size) ;
  116. void indent_line(FILE *fp) ;
  117. void put_line(FILE *fp, int len) ;
  118. void HPPCL_put_line(FILE *fp, int len) ;
  119. void fputcstr(cstr *s, FILE *fp) ;
  120. int divider_line(char *line) ;
  121. int section_start(char *line) ;
  122. void output_line(char *line,FILE *fp) ;
  123. void fill_buffer(int lines, int lines_per_page) ;
  124. int find_page_break(int lines) ;
  125. void summarize(FILE *summary, int line, int pages_printed) ;
  126. void start_format(char *line) ;
  127. void print_line(char *line) ;
  128. void print_buffer(int first, int last, int lines_per_page, int total_lines, int use_FF) ;
  129. void select_printer(char *name) ;
  130. void display_printers(void) ;
  131. int _Cdecl main(int argc, char **argv) ;
  132. #else
  133. void put_line() ;
  134. void HPPCL_put_line() ;
  135. #endif /* PROTOTYPES */
  136.  
  137. /***********************************************/
  138.  
  139. FILE *infile, *outfile ;
  140. char *input_file ;
  141.  
  142. char buffer[MAXPAGE][MAXLINE] ;
  143. char num[6] ;
  144. char summary_line[MAXLINE] ;
  145.  
  146. int pages_printed = 0 ;
  147. int page_width = 0 ;        /* page width in characters, 0 = use prtdef */
  148. int indent = 0 ;        /* number of blanks to add at start of each line */
  149. int widow_length = 10 ;     /* number of lines to scan for good place to break */
  150. int page_numbers = FALSE ;    /* add page numbers to bottom of page? */
  151. int multi_file = FALSE ;    /* printing multipart interrupt list? */
  152. int out_of_files = FALSE ;    /* hit end of last file for multipart printing? */
  153. int do_summary = FALSE ;    /* create a one-line-per-call summary? */
  154. int do_formats = FALSE ;    /* create a separate file with data structures? */
  155. int IBM_chars = FALSE ;     /* printer can handle IBM graphics characters */
  156. int boldface = FALSE ;        /* boldface titles and Return:/Notes: ? */
  157. int printer_bold = FALSE ;    /* boldface using printer control sequences? */
  158. int echo_format = FALSE ;
  159. int duplex = FALSE ;
  160. int HPPCL_mode = FALSE ;
  161. FILE *summary ;
  162. FILE *formats ;
  163. PRINTER_DEF *printer = NULL ;
  164.  
  165. int first_page = 0 ;
  166. int last_page = 9999 ;
  167.  
  168. /***********************************************/
  169.  
  170. PRINTER_DEF printers[] =
  171.    {
  172.      { "default",
  173.        CSTR(""), CSTR(""),
  174.        CSTR(""), CSTR(""), CSTR(""),
  175.        CSTR(""),
  176.        CSTR(""), CSTR(""),
  177.        CSTR(""), CSTR(""),
  178.        -1,
  179.        60,
  180.        0,
  181.        79,
  182.        put_line,
  183.        NULL,
  184.      },
  185.      { "Epson FX80",
  186.        CSTR("\033M"), CSTR(""),
  187.        CSTR("\033l\004"), CSTR("\033l\007"), CSTR("\033l\014"),
  188.        CSTR(""),
  189.        CSTR("\033P"), CSTR("\033l\000"),
  190.        CSTR("\033E"), CSTR("\033F"),
  191.        0,
  192.        60,
  193.        0,
  194.        87,    /* 96 - left margin - 1 right margin */
  195.        put_line,
  196.        NULL,
  197.      },
  198.      { "HP PCL",
  199.        CSTR("\033(8U"), CSTR(""),
  200.        CSTR("\033&a4c4L"), CSTR("\033&a8c8L"), CSTR("\033&a12c12L"),
  201.        CSTR("\033&l1S"),
  202.        CSTR("\033E"), CSTR(""),
  203.        CSTR("\033(s3B"), CSTR("\033(s0B"),
  204.        0,
  205.        69,
  206.        0,
  207.        87,    /* 96 - left margin - 1 right margin */
  208.        HPPCL_put_line,
  209.        &HPPCL_mode,
  210.      },
  211. #define HPPCL_FONT_ON_A "\033(s0p12h10v0s0b"
  212. /* HP PCL4/5 Font select: Roman-8;Upright12Pitch10PointMediumWeight */
  213. #define HPPCL_FONT_ON_B "T\033&l6.8571C"
  214. /* HP PCL4/5 Font select: End typeface select;VMI=7LPI: (48/7)-48th's inches*/
  215. #define HPPCL_IBM_LN_A    "\033&f0S\033*p-15Y\033*c"
  216. /* HP PCL4/5 IBM Line:    Push Pos;Up 15/720";Hor.Rule ???/300ths" long */
  217. #define HPPCL_IBM_LN_B    "a3b0P\033&f1S"
  218. /* HP PCL4/5 IBM Line:     3/300ths" high,Print rule;Pop Position */
  219.      { "LaserJet II",
  220.        CSTR("\033(10U"),CSTR(""),
  221.        CSTR("\033&a4c4L"), CSTR("\033&a8c8L"), CSTR("\033&a12c12L"),
  222.        CSTR(""),
  223.        CSTR("\033E"),CSTR(""),
  224.        CSTR("\033(S3B"),CSTR("\033(S0B"),
  225.        0,
  226.        54,
  227.        60,
  228.        79,
  229.        put_line,
  230.        &IBM_chars,
  231.      },
  232.    } ;
  233. #define NUM_PRINTERS (sizeof(printers)/sizeof(printers[0]))
  234.  
  235. /***********************************************/
  236.  
  237. #ifdef NEED_STRNICMP
  238. #ifdef PROTOTYPES
  239. int strnicmp(char *s1,char *s2,int len)
  240. #else
  241. int strnicmp(s1,s2,len)
  242. char *s1,*s2 ;
  243. unsigned int len ;
  244. #endif PROTOTYPES
  245. {
  246.    char c1, c2 ;
  247.  
  248.    while (*s1 && *s2 && len > 0)
  249.       {
  250.       len-- ;
  251.       c1 = (islower(*s1) ? toupper(*s1) : *s1) ;
  252.       c2 = (islower(*s2) ? toupper(*s2) : *s2) ;
  253.       if (c1 != c2 && len == 0)  /* mismatch or substrings exhausted? */
  254.      return (c1 - c2) ;
  255.       }
  256.    return 0 ;  /* strings match exactly on first 'len' characters */
  257. }
  258. #endif /* NEED_STRNICMP */
  259.  
  260. /***********************************************/
  261.  
  262. void usage()
  263. {
  264.    fputs("INTPRINT v", stderr) ;
  265.    fputs(VERSION, stderr) ;
  266.    fputs(" by Ralf Brown.  Donated to the Public Domain.\n\n",stderr) ;
  267.    fputs("Usage: intprint [options] intlist [>|>>]output\n",stderr) ;
  268.    fputs("Options:\n",stderr) ;
  269.    fputs("\t-Pname\tassume printer 'name' (-P? lists supported printers)\n",stderr) ;
  270.    fputs("\t-lN\tprint N lines per page (default depends on printer)\n",stderr) ;
  271.    fputs("\t-LN\tassume N lines on a page, use linefeeds if > #lines printed\n",stderr) ;
  272.    fputs("\t-m\tlist is in multiple parts starting with the named file\n",stderr) ;
  273.    fputs("\t-d\t(duplex) print even/odd pages with different indents\n",stderr) ;
  274.    fputs("\t-p\tadd page numbers\n",stderr) ;
  275. /*   fputs("\t-h\tadd page headers\n",stderr) ; */
  276.    fputs("\t-nN\tassume N pages have been printed from previous parts\n",stderr) ;
  277.    fputs("\t-rN:M\tprint only pages N through M\n",stderr) ;
  278.    fputs("\t-wN\tscan N lines from bottom of page for good place to break\n",stderr) ;
  279.    fputs("\t-e\tassume 'elite' mode (96 chars per line) for default printer\n",stderr) ;
  280.    fputs("\t-iN\tindent output N spaces (overridden by some printers)\n",stderr) ;
  281.    fputs("\t-b\tboldface title lines and Return:/Note:\n",stderr) ;
  282.    fputs("\t-B\tboldface using printer control codes instead of overprinting\n",stderr) ;
  283.    fputs("\t-tN\tselect typeface N for the chosen printer\n",stderr) ;
  284.    fputs("\t-I\tprinter supports IBM graphics characters\n",stderr) ;
  285.    fputs("\t-sfile\twrite a one-line-per-function summary to 'file'\n",stderr) ;
  286.    fputs("\t-ffile\twrite all data structures to 'file'\n",stderr) ;
  287.    exit(1) ;
  288. }
  289.  
  290. /***********************************************/
  291.  
  292. void fatal(msg)
  293. char *msg ;
  294. {
  295.    fputs(msg,stderr) ;
  296.    fputs("\n",stderr) ;
  297.    exit(1) ;
  298. }
  299.  
  300. /***********************************************/
  301.  
  302. void indent_line(fp)
  303. FILE *fp ;
  304. {
  305.    int ind = indent ;
  306.  
  307.    while (ind >= 8)
  308.       {
  309.       fputc('\t',fp) ;
  310.       ind -= 8 ;
  311.       }
  312.    while (ind-- > 0)
  313.       fputc(' ', fp) ;
  314. }
  315.  
  316. /***********************************************/
  317.  
  318. void put_line(fp,len)
  319. FILE *fp ;
  320. int len ;
  321. {
  322.    int i ;
  323.  
  324.    if (IBM_chars)
  325.       for (i = 0 ; i < len ; i++)
  326.      fputc(196,fp) ;  /* single horizontal line */
  327.    else
  328.       for (i = 0 ; i < len ; i++)
  329.      fputc('-',fp) ;
  330. }
  331.  
  332. /***********************************************/
  333.  
  334. void HPPCL_put_line(fp,len)
  335. FILE *fp ;
  336. int len ;
  337. {
  338.    fputs(HPPCL_IBM_LN_A,fp) ;
  339.    itoa((len * 25), num, 10) ;
  340.    fputs(num,fp) ;
  341.    fputs(HPPCL_IBM_LN_B,fp) ;
  342. }
  343.  
  344. /***********************************************/
  345.  
  346. void fputcstr(s,fp)        /* output the counted string to the given file */
  347. FILE *fp ;
  348. cstr *s ;
  349. {
  350.    int i ;
  351.  
  352.    for (i = 0 ; i < cstrlen(s) ; i++)
  353.       fputc(cstrchar(s,i),fp) ;
  354. }
  355.  
  356. /***********************************************/
  357.  
  358. int divider_line(line)
  359. char *line ;
  360. {
  361.    return strncmp(line,"--------",8) == 0 ;
  362. }
  363.  
  364. /***********************************************/
  365.  
  366. int section_start(line)
  367. char *line ;
  368. {
  369.    if (strncmp(line,"Return:",7) == 0 ||
  370.        strncmp(line,"Note:",5) == 0 ||
  371.        strncmp(line,"Notes:",6) == 0 ||
  372.        strncmp(line,"SeeAlso:",8) == 0 ||
  373.        strncmp(line,"BUG:",4) == 0)
  374.       return 1 ;
  375.    return 0 ;
  376. }
  377.  
  378. /***********************************************/
  379.  
  380. void output_line(line,fp)
  381. char *line ;
  382. FILE *fp ;
  383. {
  384.    int pos = 0 ;
  385.    char bold[10] ;
  386.  
  387.    if (boldface)
  388.       {
  389.       if (strncmp(line,"INT ",4) == 0 || strncmp(line,"Format of ",10) == 0 ||
  390.       strncmp(line,"Values ",7) == 0)
  391.      {
  392.      indent_line(fp) ;
  393.      if (printer_bold)
  394.         {
  395.         fputcstr(&printer->bold_on,fp) ;
  396.         fputs(line,fp) ;
  397.         fputcstr(&printer->bold_off,fp) ;
  398.         line = NULL ;
  399.         }
  400.      else
  401.         {
  402.         fputs(line,fp) ;
  403.         fputc('\r',fp) ;
  404.         }
  405.      }
  406.       else if (section_start(line))
  407.      {
  408.      strncpy(bold,line,sizeof bold) ;
  409.      *strchr(bold,':') = '\0' ;
  410.      indent_line(fp) ;
  411.      if (printer_bold)
  412.         {
  413.         fputcstr(&printer->bold_on,fp) ;
  414.         fputs(bold,fp) ;
  415.         fputcstr(&printer->bold_off,fp) ;
  416.         pos = strlen(bold) ;     /* we're no longer at the left edge of the */
  417.         line += pos ;         /* line, so figure out where we are */
  418.         }
  419.      else
  420.         {
  421.         fputs(bold,fp) ;
  422.         fputc('\r',fp) ;
  423.         }
  424.      }
  425.       }
  426.    if (line && *line)
  427.       {
  428.       if (pos == 0)        /* are we currently at the left edge of the line? */
  429.      indent_line(fp) ;  /* if yes, indent the desired amount */
  430.       if (indent % 8)
  431.      {
  432.      while (*line)
  433.         {
  434.         if (*line == '\t')
  435.            do {
  436.           fputc(' ',fp) ;
  437.           } while (++pos % 8) ;
  438.         else
  439.            {
  440.            fputc(*line,fp) ;
  441.            pos++ ;
  442.            }
  443.         line++ ;
  444.         }
  445.      }
  446.       else
  447.      fputs(line,fp) ;
  448.       }
  449.    fputc('\n',fp) ;
  450. }
  451.  
  452. /***********************************************/
  453.  
  454. void get_line(buf,size)
  455. char *buf ;
  456. int size ;
  457. {
  458.    int last ;
  459.  
  460.    buf[0] = '\0' ;
  461.    if (out_of_files)
  462.       return ;
  463.    fgets(buf,size,infile) ;
  464.    if ((feof(infile) || buf[0] == '\0'))
  465.       if (multi_file)
  466.      {
  467.      FILE *tempfile ;
  468.  
  469.      last = strlen(input_file) - 1 ;
  470.      input_file[last]++ ;
  471.      if ((tempfile = fopen(input_file,"r")) != NULL)
  472.         {
  473.         fclose(infile) ;
  474.         infile = tempfile ;
  475.         fgets(buf,size,infile) ;
  476.         }
  477.      else
  478.         {
  479.         out_of_files = TRUE ;
  480.         return ;
  481.         }
  482.      }
  483.       else
  484.      out_of_files = TRUE ;
  485.    last = strlen(buf) - 1 ;
  486.    if (last < 0)
  487.       last = 0 ;
  488.    if (buf[last] == '\n')
  489.       buf[last] = '\0' ;  /* strip the newline */
  490. }
  491.  
  492. /***********************************************/
  493.  
  494. void fill_buffer(lines,lines_per_page)
  495. int lines, lines_per_page ;
  496. {
  497.    int i ;
  498.  
  499.    if (lines)
  500.       for (i = lines ; i < lines_per_page ; i++)
  501.      strcpy(buffer[i-lines], buffer[i]) ;
  502.    else
  503.       lines = lines_per_page ;
  504.    for (i = lines_per_page - lines ; i < lines_per_page ; i++)
  505.       get_line(buffer[i], sizeof(buffer[i])) ;
  506. }
  507.  
  508. /***********************************************/
  509.  
  510. int find_page_break(lines)
  511. int lines ;
  512. {
  513.    int i ;
  514.  
  515.    for (i = 0 ; i < widow_length ; i++)
  516.       {
  517.       if (strcmp(buffer[lines-i-1],"\n") == 0 ||
  518.       strlen(buffer[lines-i-1]) == 0 ||
  519.       divider_line(buffer[lines-i-1]) ||
  520.       section_start(buffer[lines-i]))
  521.      return lines - i ;
  522.       }
  523.    return lines ;
  524. }
  525.  
  526. /***********************************************/
  527.  
  528. void summarize(summary, line, pages_printed)
  529. FILE *summary ;
  530. int line, pages_printed ;
  531. {
  532.    char *s ;
  533.    int i ;
  534.    int max_descrip ;
  535.    int len ;
  536.  
  537.    s = buffer[line] ;
  538.    if (strncmp(s, "INT ", 4) == 0)   /* start of an entry? */
  539.       {
  540.       summary_line[3] = summary_line[0] = ' ' ;
  541.       summary_line[1] = s[4] ;     /* output interrupt number */
  542.       summary_line[2] = s[5] ;
  543.       summary_line[4] = '\0' ;
  544.       len = 4 ;
  545.       s = buffer[line+1] ;
  546.       while (*s && isspace(*s))
  547.      s++ ;
  548.       if (strncmp(s,"AX",2) == 0)
  549.      i = 4 ;
  550.       else if (strncmp(s,"AH",2) == 0)
  551.      i = 2 ;
  552.       else
  553.      i = 0 ;
  554.       if (i)
  555.      {
  556.      while (*s && *s != '=')
  557.         s++ ;
  558.      s++ ;    /* skip the equal sign */
  559.      while (*s && isspace(*s))
  560.         s++ ;
  561.      if (strchr("0123456789ABCDEFabcdef",*s) != NULL &&
  562.          strchr("0123456789ABCDEFabcdef",s[1]) != NULL)
  563.         {
  564.         summary_line[len++] = *s++ ;
  565.         summary_line[len++] = *s++ ;
  566.         summary_line[len++] = ' ' ;
  567.         if (i == 4)
  568.            {
  569.            summary_line[len++] = *s++ ;
  570.            summary_line[len++] = *s ;
  571.            }
  572.         else
  573.            {
  574.            summary_line[len++] = '-' ;
  575.            summary_line[len++] = '-' ;
  576.            }
  577.         summary_line[len++] = ' ' ;
  578.         }
  579.      else
  580.         {
  581.         /* wasn't legal digit, so no numbers */
  582.         strcpy(summary_line+len,"-- -- ") ;
  583.         len += 6 ;
  584.         }
  585.      }
  586.       else
  587.      {
  588.      strcpy(summary_line+len,"-- -- ") ;
  589.      len += 6 ;
  590.      }
  591.       if (page_numbers)
  592.      {
  593.      itoa(pages_printed,num,10) ;
  594.      for (i = strlen(num) ; i < 3 ; i++)
  595.         summary_line[len++] = ' ' ;
  596.      strcpy(summary_line+len,num) ;
  597.      len += strlen(num) ;
  598.      summary_line[len++] = ' ' ;
  599.      }
  600.       s = buffer[line] + 7 ;  /* find function description */
  601.       while (*s && !isspace(*s))
  602.      s++ ;
  603.       while (*s && isspace(*s))
  604.      s++ ;
  605.       max_descrip = (page_numbers ? MAXLINE-16 : MAXLINE-12) ;
  606.       for (i = 0 ; i < max_descrip && *s ; i++)
  607.      summary_line[len++] = *s++ ;
  608.       summary_line[len] = '\0' ;
  609.       if (do_summary)
  610.      output_line(summary_line,summary) ;
  611.       }
  612. }
  613.  
  614. /***********************************************/
  615.  
  616. void start_format(line)
  617. char *line ;
  618. {
  619.    indent_line(formats) ;
  620.    (*printer->put_line)(formats,79) ;
  621.    fputc('\n',formats) ;
  622.    indent_line(formats) ;
  623.    fputs(summary_line,formats) ;
  624.    fputc('\n',formats) ;
  625.    indent_line(formats) ;
  626.    fputc('\t',formats) ;
  627.    fputs(line+10,formats) ;
  628.    fputc('\n',formats) ;
  629.    echo_format = TRUE ;
  630. }
  631.  
  632. /***********************************************/
  633.  
  634. void print_line(line)
  635. char *line ;
  636. {
  637.    if (*line)
  638.       {
  639.       if (divider_line(line))
  640.      {
  641.      indent_line(outfile) ;
  642.      (*printer->put_line)(outfile,79) ;
  643.      fputc('\n', outfile) ;
  644.      echo_format = FALSE ;
  645.      }
  646.       else
  647.      {
  648.      output_line(line, outfile) ;
  649.      if (echo_format)
  650.         output_line(line,formats) ;
  651.      }
  652.       }
  653.    else
  654.       {
  655.       fputc('\n', outfile) ;
  656.       echo_format = FALSE ;
  657.       }
  658. }
  659.  
  660. /***********************************************/
  661.  
  662. void print_buffer(first,last,lines_per_page,total_lines,use_FF)
  663. int first, last, lines_per_page, total_lines ;
  664. int use_FF ;
  665. {
  666.    int i, ind ;
  667.  
  668.    pages_printed++ ;
  669.    for (i = first ; i < last ; i++)
  670.       {
  671.       if (pages_printed >= first_page && pages_printed <= last_page)
  672.      print_line(buffer[i]) ;
  673.       if (do_summary || do_formats)  /* need summary lines if doing formats */
  674.      summarize(summary,i,pages_printed) ;
  675.       if (do_formats && strncmp(buffer[i],"Format of ",10) == 0)
  676.      start_format(buffer[i]) ;
  677.       }
  678.    if (pages_printed >= first_page && pages_printed <= last_page)
  679.       {
  680.       if (page_numbers)
  681.      {
  682.      for (i = last - first ; i < lines_per_page - 1 ; i++)
  683.         fputc('\n', outfile) ;
  684.      indent_line(outfile) ;
  685.      for (ind = 0 ; ind < 38 ; ind++) /* normal indent + 38 spaces */
  686.         fputc(' ', outfile) ;
  687.      fputs("- ", outfile) ;
  688.      itoa(pages_printed, num, 10) ;
  689.      fputs(num, outfile) ;
  690.      fputs(" -\n", outfile) ;
  691.      }
  692.       if (use_FF)
  693.      fputc('\f', outfile) ;
  694.       else
  695.      for (i = page_numbers?lines_per_page:(last-first) ; i<total_lines ; i++)
  696.         fputc('\n', outfile) ;
  697.       if (duplex)
  698.      {
  699.      if ((pages_printed % 2) == 1)    /* next page even or odd? */
  700.         fputcstr(&printer->marginl, outfile) ;    /* even page */
  701.      else
  702.         fputcstr(&printer->marginr, outfile) ;    /* odd page */
  703.      }
  704.       }
  705. }
  706.  
  707. /***********************************************/
  708.  
  709. void display_printers()
  710. {
  711.    int i ;
  712.    
  713.    fputs("Valid printer names are:\n",stderr) ;
  714.    for (i = 0 ; i < NUM_PRINTERS ; i++)
  715.       {
  716.       fputc('\t',stderr) ;
  717.       fputs(printers[i].name,stderr) ;
  718.       fputc('\n',stderr) ;
  719.       }
  720.    fputs("When entering the printer name, use either a dash or an underscore\n",stderr) ;
  721.    fputs("in place of blanks.  Case is ignored, and the name may be abbreviated\n",stderr) ;
  722.    fputs("to the shortest unique prefix.\n",stderr) ;
  723.    exit(1) ;
  724. }
  725.  
  726. /***********************************************/
  727.  
  728. void select_printer(name)
  729. char *name ;
  730. {
  731.    int i, len, prt = -1 ;
  732.    
  733.    len = strlen(name) ;
  734.    for (i = 0 ; i < len ; i++)        /* convert dashes and underscores to blanks */
  735.       if (name[i] == '-' || name[i] == '_')
  736.      name[i] = ' ' ;
  737.    for (i = 0 ; i < NUM_PRINTERS ; i++)
  738.       if (strnicmp(name,printers[i].name,strlen(name)) == 0)
  739.      if (prt == -1)
  740.         prt = i ;
  741.      else
  742.         fatal("Ambiguous printer name!  Use -P? to list printers.") ;
  743.    if (prt == -1)
  744.       fatal("Unknown printer name!  Use -P? to list printers.") ;
  745.    else
  746.       printer = &printers[prt] ;
  747. }
  748.  
  749. /***********************************************/
  750.  
  751. int _Cdecl main(argc,argv)
  752. int argc ;
  753. char *argv[] ;
  754. {
  755.    int lines_per_page = -1 ;
  756.    int total_lines = -1 ;
  757.    int use_FF = TRUE ;
  758.    int last_line ;
  759.    int body_lines ;
  760.    char *typeface = NULL ;
  761.    char *summary_file = NULL ;
  762.    char *formats_file = NULL ;
  763.    char *last_page_num ;
  764.    
  765.    if (argc == 1 && isatty(0))
  766.       usage() ;   /* give help if invoked with no args and keybd input */
  767.    while (argc >= 2 && argv[1][0] == '-')
  768.       {
  769.       switch (argv[1][1])
  770.      {
  771.      case 'e':
  772.         indent = 8 ;
  773.         page_width = 87 ;  /* 96 - indent - 1 right margin */
  774.         break ;
  775.      case 'P':
  776.         if (argv[1][2] == '?')
  777.            display_printers() ;
  778.         else
  779.            select_printer(argv[1]+2) ;
  780.         break ;
  781.      case 'I':
  782.         IBM_chars = TRUE ;
  783.         break ;
  784.      case 'p':
  785.         page_numbers = TRUE ;
  786.         break ;
  787.      case 'h':   /* page headers */
  788.         /* nothing yet */
  789.         break ;
  790.      case 'B':
  791.         printer_bold = TRUE ;
  792.         /* fall through to -b */
  793.      case 'b':
  794.         boldface = TRUE ;
  795.         break ;
  796.      case 'd':
  797.         duplex = TRUE ;
  798.         break ;
  799.      case 'm':
  800.         multi_file = TRUE ;
  801.         break ;
  802.      case 'n':
  803.         pages_printed = atoi(argv[1]+2) ;
  804.         break ;
  805.      case 'r':
  806.         first_page = atoi(argv[1]+2) ;
  807.         last_page_num = strchr(argv[1]+2, ':') ;
  808.         last_page = last_page_num ? atoi(last_page_num+1) : 0 ;
  809.         if (last_page == 0)
  810.            last_page = 9999 ;
  811.         break ;
  812.      case 'i':
  813.         indent = atoi(argv[1]+2) ;
  814.         break ;
  815.      case 's':
  816.         summary_file = argv[1]+2 ;
  817.         break ;
  818.      case 'f':
  819.         formats_file = argv[1]+2 ;
  820.         break ;
  821.      case 'w':
  822.         widow_length = atoi(argv[1]+2) ;
  823.         break ;
  824.      case 'l':
  825.         lines_per_page = atoi(argv[1]+2) ;
  826.         break ;
  827.      case 'L':
  828.         total_lines = atoi(argv[1]+2) ;
  829.         break ;
  830.      case 't':
  831.         typeface = argv[1]+2 ;
  832.         break ;
  833.      default:
  834.         usage() ;
  835.      }
  836.       argv++ ;
  837.       argc-- ;
  838.       }
  839.    if (printer == NULL)
  840.       select_printer("default") ;
  841.    /* apply any necessary overrides to parameters */
  842.    if (printer->indent != -1)
  843.       indent = printer->indent ;
  844.    if (lines_per_page <= 0)
  845.       lines_per_page = printer->lines_per_page ;
  846.    if (total_lines <= 0)
  847.       total_lines = printer->page_length ;
  848.    if (page_width <= 0)
  849.       page_width = printer->page_width ;
  850.    if (printer->flag)
  851.       *(printer->flag) = TRUE ;
  852.    if (cstrlen(&printer->bold_on) == 0)  /* control sequences for bold? */
  853.       printer_bold = FALSE ;        /* if not, don't try to use them */
  854.  
  855.    /* open the summary file, if any */
  856.    if (summary_file && *summary_file)
  857.       if ((summary = fopen(summary_file, pages_printed ? "a":"w")) != NULL)
  858.      do_summary = TRUE ;
  859.       else
  860.      fputs("unable to open summary file\n", stderr) ;
  861.    /* open the data formats file, if any */
  862.    if (formats_file && *formats_file)
  863.       if ((formats = fopen(formats_file, pages_printed ? "a":"w")) != NULL)
  864.      do_formats = TRUE ;
  865.       else
  866.      fputs("unable to open formats file\n", stderr) ;
  867.    if (total_lines <= lines_per_page)
  868.       {
  869.       total_lines = lines_per_page ;
  870.       use_FF = TRUE ;
  871.       }
  872.    else
  873.       use_FF = FALSE ;
  874.    if (argc == 2 || argc == 3)
  875.       {
  876.       input_file = argv[1] ;
  877.       infile = fopen(input_file,"r") ;
  878.       if (infile == NULL)
  879.      fatal("unable to open input file") ;
  880.       if (argc == 3)
  881.      {
  882.      outfile = fopen(argv[2],(pages_printed?"a":"w")) ;
  883.      if (outfile == NULL)
  884.         fatal("unable to open output file") ;
  885.      }
  886.       else
  887.      outfile = stdout ;
  888.       }
  889.    else
  890.       usage() ;
  891.    if (lines_per_page < 20 || lines_per_page > MAXPAGE)
  892.       {
  893.       fputs("Surely you jest!  At least 20 and at most 200 lines per page.\n\n", stderr) ;
  894.       usage() ;
  895.       }
  896.    if (widow_length < 3 || widow_length > lines_per_page / 2)
  897.       {
  898.       fputs("Widow lines (-w) must be set to at least 3 and at most one-half of the\n",stderr) ;
  899.       fputs("page length.  Using default of 10 lines.\n",stderr) ;
  900.       widow_length = 10 ;
  901.       }
  902. #ifdef __TURBOC__
  903.    setvbuf(infile,NULL,_IOFBF,10240) ;    /* use larger disk buffers */
  904.    setvbuf(outfile,NULL,_IOFBF,10240) ; /* for better performance */
  905.    if (do_summary)
  906.       setvbuf(summary,NULL,_IOFBF,4096) ;
  907.    if (do_formats)
  908.       setvbuf(formats,NULL,_IOFBF,4096) ;
  909. #endif /* __TURBOC__ */
  910.    /* set up the printer */
  911.    fputcstr(&printer->init1,outfile) ;
  912.    fputcstr(&printer->init2,outfile) ;
  913.    if (HPPCL_mode)
  914.       {
  915.       fputs(HPPCL_FONT_ON_A,outfile) ;
  916.       if (typeface)
  917.      fputs(typeface,outfile) ;
  918.       else
  919.      fputs("8",outfile) ;
  920.       fputs(HPPCL_FONT_ON_B,outfile) ;
  921.       }
  922.    if (duplex)
  923.       {
  924.       fputcstr(&printer->duplex_on,outfile) ;
  925.       if ((pages_printed % 2) == 1)    /* next page odd or even? */
  926.      fputcstr(&printer->marginl,outfile) ;    /* even */
  927.       else
  928.      fputcstr(&printer->marginr,outfile) ;    /* odd */
  929.       }
  930.    else
  931.       fputcstr(&printer->marginc,outfile) ;    /* non-duplex, so center */
  932.    /* start the summary file */
  933.    if (do_summary && pages_printed == 0)
  934.       {       /* create header, but only on first part */
  935.       /* set up the printer */
  936.       fputcstr(&printer->init1,summary) ;
  937.       fputcstr(&printer->init2,summary) ;
  938.       fputcstr(&printer->marginc,summary) ;
  939.       indent_line(summary) ;
  940.       fputs("\t\t\t\tInterrupt Summary\n",summary) ;
  941.       indent_line(summary) ;
  942.       fputs("\t\t\t\t", summary) ;
  943.       (*printer->put_line)(summary,17) ;
  944.       fputs("\n\n",summary) ;
  945.       indent_line(summary) ;
  946.       fputs("INT AH AL", summary) ;
  947.       if (page_numbers)
  948.      fputs(" Page", summary) ;
  949.       fputs("\t\t\tDescription\n", summary) ;
  950.       indent_line(summary) ;
  951.       (*printer->put_line)(summary,page_width) ;
  952.       fputc('\n', summary) ;
  953.       }
  954.    /* start the data formats file */
  955.    if (do_formats && pages_printed == 0)
  956.       {       /* create header, but only on first part */
  957.       /* set up the printer */
  958.       fputcstr(&printer->init1,formats) ;
  959.       fputcstr(&printer->init2,formats) ;
  960.       fputcstr(&printer->marginc,formats) ;
  961.       indent_line(formats) ;
  962.       fputs("\t\t\tData Structure Formats\n", formats) ;
  963.       indent_line(formats) ;
  964.       fputs("\t\t\t", formats) ;
  965.       (*printer->put_line)(formats,22) ;
  966.       fputs("\n\n", formats) ;
  967.       indent_line(formats) ;
  968.       fputs("INT AH AL", formats) ;
  969.       if (page_numbers)
  970.      fputs(" Page", formats) ;
  971.       fputs("\t\tData Structure\n", formats) ;
  972.       }
  973.    if (page_numbers)
  974.       body_lines = lines_per_page - 2 ;
  975.    else
  976.       body_lines = lines_per_page ;
  977.    last_line = 0 ;
  978.    while (!feof(infile) && !out_of_files)
  979.       {
  980.       fill_buffer(last_line,body_lines) ;
  981.       last_line = find_page_break(body_lines) ;
  982.       print_buffer(0,last_line,lines_per_page,total_lines,use_FF) ;
  983.       }
  984.    if (last_line < body_lines)
  985.       print_buffer(last_line,body_lines,lines_per_page,total_lines,use_FF) ;
  986.    /* reset the printer */
  987.    fputcstr(&printer->term1,outfile) ;
  988.    fputcstr(&printer->term2,outfile) ;
  989.    fflush(outfile) ;
  990.    itoa(pages_printed, num, 10) ;
  991.    fputs(num, stderr) ;
  992.    fputs(" pages\n", stderr) ;
  993.    if (do_summary)
  994.       {
  995.       /* reset the printer */
  996.       fputcstr(&printer->term1,summary) ;
  997.       fputcstr(&printer->term2,summary) ;
  998.       fclose(summary) ;
  999.       }
  1000.    if (do_formats)
  1001.       {
  1002.       /* reset the printer */
  1003.       fputcstr(&printer->term1,formats) ;
  1004.       fputcstr(&printer->term2,formats) ;
  1005.       fclose(formats) ;
  1006.       }
  1007.    fclose(infile) ;
  1008.    return 0 ;
  1009. }
  1010.